*&---------------------------------------------------------------------*
*& Report ZEX_LISTING_39                                               *
*&---------------------------------------------------------------------*
*& Created By: James Wood (james.wood@bowdarkconsulting.com)           *
*& Created On: 12/12/2008                                              *
*& Purpose:    This program demonstrates the use of a custom date API  *
*&             as described in Listing 3.9.                            *
*&---------------------------------------------------------------------*
REPORT zex_listing_39.

*----------------------------------------------------------------------*
*       CLASS lcl_date DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_date DEFINITION.
  PUBLIC SECTION.
    METHODS: set_month IMPORTING VALUE(iv_month) TYPE numc2
                       EXCEPTIONS invalid_date,
             set_day   IMPORTING value(iv_day) TYPE numc2
                       EXCEPTIONS invalid_date,
             set_year  IMPORTING VALUE(iv_year) TYPE numc4
                       EXCEPTIONS invalid_date.

  PRIVATE SECTION.
    DATA: date TYPE scals_date.
ENDCLASS.                    "lcl_date DEFINITION

*----------------------------------------------------------------------*
*       CLASS lcl_date IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_date IMPLEMENTATION.
  METHOD set_month.
    IF ( ( iv_month >= '01' ) AND ( iv_month <= '12' ) ).
      date-month = iv_month.
    ELSE.
      RAISE invalid_date.
    ENDIF.
  ENDMETHOD.

  METHOD set_day.
*   Method-Local Data Declarations:
    DATA: lv_month_end TYPE i.         "Last Day of Month

*   Determine the last day of the month:
    CASE date-month.
      WHEN 1.
        lv_month_end = 31.
      WHEN 2.
        "...
      WHEN 12.
        "...
    ENDCASE.

*   Check the proposed day value:
    IF iv_day LT 1 OR iv_day GT lv_month_end.
      RAISE invalid_date.
    ELSE.
      date-day = iv_day.
    ENDIF.
  ENDMETHOD.                    "set_day

  METHOD set_year.
    date-year = iv_year.
  ENDMETHOD.
ENDCLASS.                    "lcl_date IMPLEMENTATION

*----------------------------------------------------------------------*
* START-OF-SELECTION Event Module                                      *
*----------------------------------------------------------------------*
START-OF-SELECTION.
  PERFORM test_date_api.

*&---------------------------------------------------------------------*
*&      Form  test_date_api
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
FORM test_date_api.

* Local Data Declarations:
  DATA: lr_date TYPE REF TO lcl_date.

* Create a new date object:
  CREATE OBJECT lr_date.

* Set the date to 01/13/2009:
  CALL METHOD lr_date->set_month
    EXPORTING
      iv_month = '01'
    EXCEPTIONS
      invalid_date = 1
      others       = 2.

  CALL METHOD lr_date->set_day
    EXPORTING
      iv_day  = '13'
    EXCEPTIONS
      invalid_date = 1
      others       = 2.

  CALL METHOD lr_date->set_year
    EXPORTING
      iv_year      = '2009'
    EXCEPTIONS
      invalid_date = 1
      others       = 2.

* The following line would produce a syntax error as access to the
* private date attribute is forbidden:
*  lr_date->date-day = '99'.

* Try to adjust the day value to an invalid value:
  CALL METHOD lr_date->set_day
    EXPORTING
      iv_day       = '99'
    EXCEPTIONS
      invalid_date = 1
      others       = 2.

  IF sy-subrc NE 0.
    WRITE: / 'You specified an invalid day value.'.
  ENDIF.

ENDFORM.                    "test_date_api